/*
 * Marmoset Add-In for Microsoft Visual Studio
 *
 * Copyright (C) 2007, David H. Hovemeyer
 * Copyright (C) 2007, Fidel K. Estrella
 *
 * This program is free software licensed under the
 * terms of the GNU General Public License, version 2.
 * See the file "COPYING.txt" for details.
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Marmoset
{
    /// <summary>
    /// A class for reading/writing key/value pairs to/from text files.
    /// Intended to be compatible with Java properties files.
    /// </summary>
    class Properties
    {
        #region Private Field
        private Dictionary<string, string> _settings;
        #endregion

        #region Constructor
        /// <summary>
        /// Constructor.
        /// Creates empty Properties object.
        /// </summary>
        public Properties()
        {
            _settings = new Dictionary<string, string>();
        }
        #endregion

        #region Public Members
        /// <summary>
        /// Set a property, overwriting any previous property with
        /// the same key.
        /// </summary>
        /// <param name="key">the key</param>
        /// <param name="value">the value associated with the key</param>
        public void Set(string key, string value)
        {
            if (!_settings.ContainsKey(key))
            {
                _settings[key] = value;
            }
        }

        /// <summary>
        /// Get value associated with given key.
        /// </summary>
        /// <param name="key">the key</param>
        /// <returns>value associated with key, or null if key does not exist</returns>
        public string Get(string key)
        {
            return _settings.ContainsKey(key) ? _settings[key] : null;
        }

        /// <summary>
        /// Remove given key and its associated value from the properties.
        /// </summary>
        /// <param name="key">key to remove</param>
        public void Remove(string key)
        {
            if (_settings.ContainsKey(key))
            {
                _settings.Remove(key);
            }
        }

        /// <summary>
        /// Get collection of all keys in the object.
        /// </summary>
        /// <returns>collection of all keys in the object</returns>
        public ICollection<string> GetKeys()
        {
            return _settings.Keys;
        }

        /// <summary>
        /// Read properties from given file.  Throws an exception if unsuccessful.
        /// </summary>
        /// <param name="fileName">name of a properties file</param>
        public void Read(string fileName)
        {
            Read(File.OpenText(fileName));
        }

        /// <summary>
        /// Read properties from given StreamReader.
        /// The StreamReader is guaranteed to be closed.
        /// Throws exception if unsuccessful.
        /// </summary>
        /// <param name="reader">a StreamReader to read properties from</param>
        public void Read(StreamReader reader)
        {
            using (reader)
            {
                while (!reader.EndOfStream)
                {
                    string line = reader.ReadLine();
                    if (line == null)
                    {
                        break;
                    }

                    line = line.Trim();
                    if (line.StartsWith("#"))
                    {
                        // Comment
                        continue;
                    }

                    int eq = line.IndexOf('=');
                    if (eq < 0)
                    {
                        // Hmm...invalid syntax
                        continue;
                    }

                    string key = line.Substring(0, eq).Trim();
                    string val = line.Substring(eq + 1).Trim();

                    _settings.Add(key, val);
                }
                reader.Close();
            }
        }

        /// <summary>
        /// Write properties to a file.
        /// Throws an exception if unsuccessful.
        /// </summary>
        /// <param name="fileName">name of file to write</param>
        public void Write(string fileName)
        {
            Write(File.CreateText(fileName));
        }

        /// <summary>
        /// Write properties to given StreamWriter.
        /// The StreamWriter is guaranteed to be closed.
        /// Throws an exception if unsuccessful.
        /// </summary>
        /// <param name="writer">StreamWriter to write properties to</param>
        public void Write(StreamWriter writer)
        {
            using (writer)
            {
                for (IEnumerator<string> e = _settings.Keys.GetEnumerator(); e.MoveNext(); )
                {
                    string key = e.Current;
                    string val = _settings[key];

                    writer.WriteLine(key + "=" + val);
                }
            }
        }
        #endregion
    }
}
